package ru.zombator.taskman.dbadmin;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;

import ru.zombator.taskman.core.dbclient.IDbClient;
import ru.zombator.taskman.core.dbclient.impl.DbClientFactory;
import ru.zombator.taskman.core.domain.IManager;
import ru.zombator.taskman.core.domain.IPerson;
import ru.zombator.taskman.core.domain.IWorker;
import ru.zombator.taskman.dbadmin.actions.AddUserAction;
import ru.zombator.taskman.dbadmin.actions.DeleteUserAction;
import ru.zombator.taskman.dbadmin.actions.ModifyUserAction;
import ru.zombator.taskman.dbadmin.actions.RefreshListAction;

/**
 * Основной класс приложения "администратор БД"
 * 
 * @author nvamelichev
 *
 */
public class AdminApp implements Runnable, ImageNames {
	// визуальные компоненты ///////////////////////////////////////////////////
	private TableViewer usersTable;
	private ImageRegistry registry;
	private IDbClient client;
	private Shell shell;
	
	////////////////////////////////////////////////////////////////////////////

	/**
	 * список пользователей
	 */
	private List<IPerson> persons = new ArrayList<IPerson>();
	
	////////////////////////////////////////////////////////////////////////////
	
	/**
	 * @return	клиент БД
	 */
	public IDbClient getClient() {
		return client;
	}

	/**
	 * @return просмотрщик таблицы пользователей
	 */
	public TableViewer getUsersTable() {
		return usersTable;
	}
	
	/**
	 * @return	локальный список пользователей,
	 * используемый при отображении таблицы
	 */
	public List<IPerson> getLocalUserList() {
		return persons;
	}	

	/**
	 * @return реестр изображений
	 */
	public ImageRegistry getRegistry() {
		return registry;
	}

	/**
	 * @return основное окно
	 */
	public Shell getShell() {
		return shell;
	}

	public static void main(String[] args) {
		new Thread(new AdminApp()).start();
	}

	/**
	 * Основной цикл работы программы.
	 */
	@Override
	public void run() {
		initDbClient();

		Display display = new Display();
		initRegistry(display);

		shell = new Shell(display);
		createContents();
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

	/**
	 * инициализирует клиента БД
	 */
	private void initDbClient() {
		client = DbClientFactory.newDbClient();
	}

	/**
	 * создает содержимое главного окна
	 * 
	 * @param shell
	 *            - главное окно
	 */
	private void createContents() {
		shell.setText("Администратор БД");
		shell.setImage(registry.get(LOGO));

		createMenu();
		createTable();
		createContextMenu();
		updateList();
	}

	/**
	 * Добавляет элементы меню "пользователи" к заданному меню.
	 * 
	 * @param root
	 *            - корень меню
	 */
	private void addMenuItems(MenuManager root) {
		root.add(new AddUserAction(this));
		root.add(new ModifyUserAction(this));
		root.add(new DeleteUserAction(this));
		root.add(new Separator());
		root.add(new RefreshListAction(this));
	}

	/**
	 * Создает главное меню
	 */
	private void createMenu() {
		MenuManager root = new MenuManager("");
		MenuManager users = new MenuManager("Пользователи");
		root.add(users);

		addMenuItems(users);

		Menu menu = root.createMenuBar((Decorations) shell);
		shell.setMenuBar(menu);
	}

	/**
	 * Создает контекстное меню таблицы
	 */
	private void createContextMenu() {
		MenuManager root = new MenuManager("");
		addMenuItems(root);

		Menu popup = root.createContextMenu(usersTable.getControl());
		usersTable.getTable().setMenu(popup);
	}

	/**
	 * Создает саму таблицу
	 */
	private void createTable() {
		shell.setLayout(new FillLayout());
		// вид таблицы
		usersTable = new TableViewer(shell, SWT.MULTI | SWT.BORDER
				| SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION);
		usersTable.getTable().setHeaderVisible(true);
		usersTable.getTable().setLinesVisible(true);
		usersTable.getTable().addControlListener(new TableWidthListener());

		// колонки
		TableViewerColumn columnName = new TableViewerColumn(usersTable,
				SWT.LEFT);
		columnName.getColumn().setText("Имя");
		columnName.getColumn().pack();

		TableViewerColumn columnRole = new TableViewerColumn(usersTable,
				SWT.LEFT);
		columnRole.getColumn().setText("Роль");
		columnRole.getColumn().pack();

		TableViewerColumn columnIP = new TableViewerColumn(usersTable, SWT.LEFT);
		columnIP.getColumn().setText("IP-адрес");
		columnIP.getColumn().pack();

		usersTable.setComparator(new ViewerComparator() {
			@Override
			public int compare(Viewer viewer, Object e1, Object e2) {
				IPerson p1 = (IPerson) e1;
				IPerson p2 = (IPerson) e2;
				
				if (p1 instanceof IManager && p2 instanceof IWorker) {
					return -1;
				} else if (p1 instanceof IWorker && p2 instanceof IManager) {
					return 1;
				} else {
					return p1.getName().compareTo(p2.getName());
				}
				
			}
		});
		
		usersTable.setContentProvider(new ArrayContentProvider());
		usersTable.setInput(persons);
		columnName.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				if (element instanceof IPerson) {
					return ((IPerson) element).getName();
				}
				return super.getText(element);
			}
			
			@Override
			public Color getBackground(Object element) {
				return new RankDecorator().getBackground(element);
			}
		});
		columnRole.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				if (element instanceof IWorker) {
					return "исполнитель";
				} else if (element instanceof IManager) {
					return "менеджер";
				}
				return super.getText(element);
			}
			
			@Override
			public Color getBackground(Object element) {
				return new RankDecorator().getBackground(element);
			}			
		});
		columnIP.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				if (element instanceof IPerson) {
					return ((IPerson) element).getIpAddress();
				}
				return null;
			}
			
			@Override
			public Color getBackground(Object element) {
				return new RankDecorator().getBackground(element);
			}			
		});
		
		usersTable.addDoubleClickListener(new IDoubleClickListener() {
			@Override
			public void doubleClick(DoubleClickEvent event) {
				if (!event.getSelection().isEmpty()) {
					new ModifyUserAction(AdminApp.this).run();
				}
			}
		});
	}

	/**
	 * инициализирует реестр изображений
	 * @param display - экран, на котором изображения будут отображаться
	 */
	private void initRegistry(Display display) {
		registry = new ImageRegistry(display);
		registry.put(LOGO, ImageDescriptor.createFromURL(getClass()
				.getResource("/icons/users.gif")));
		registry.put(ADD_USER, ImageDescriptor.createFromURL(getClass()
				.getResource("/icons/add_user.gif")));
		registry.put(DELETE_USER, ImageDescriptor.createFromURL(getClass()
				.getResource("/icons/delete_user.gif")));
		registry.put(WIZ_LOGO, ImageDescriptor.createFromURL(getClass()
				.getResource("/icons/wizard_logo.gif")));		
	}

	/**
	 * обновляет список элементов
	 */
	private void updateList() {
		new RefreshListAction(this).run();
	}
}
